"""
企业级金融数据MCP服务系统 - 基金数据模型
提供完整的基金相关数据SQLAlchemy ORM模型定义
"""

from datetime import datetime, date
from decimal import Decimal
from typing import Optional, Dict, Any
from sqlalchemy import String, DateTime, Date, Boolean, Integer, Numeric, Text, Index, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy.dialects.postgresql import JSONB

from .base import BaseFinancialModel, DataVersionMixin, SyncStatusMixin, PartitionMixin


class FundBasicInfo(BaseFinancialModel, SyncStatusMixin):
    """
    基金基本信息模型
    存储基金的基础信息，如基金代码、名称、类型等
    """
    __tablename__ = "fund_basic_info"
    
    # 基金代码
    fund_code: Mapped[str] = mapped_column(String(20), nullable=False, comment="基金代码")
    
    # 基金名称
    fund_name: Mapped[str] = mapped_column(String(200), nullable=False, comment="基金名称")
    
    # 基金简称
    fund_short_name: Mapped[Optional[str]] = mapped_column(String(100), nullable=True, comment="基金简称")
    
    # 基金类型：股票型, 债券型, 混合型, 货币型, QDII等
    fund_type: Mapped[Optional[str]] = mapped_column(String(50), nullable=True, comment="基金类型")
    
    # 基金子类型
    fund_sub_type: Mapped[Optional[str]] = mapped_column(String(50), nullable=True, comment="基金子类型")
    
    # 投资类型：开放式, 封闭式, ETF, LOF等
    invest_type: Mapped[Optional[str]] = mapped_column(String(50), nullable=True, comment="投资类型")
    
    # 基金管理人代码
    manager_code: Mapped[Optional[str]] = mapped_column(String(20), nullable=True, comment="基金管理人代码")
    
    # 基金管理人名称
    manager_name: Mapped[Optional[str]] = mapped_column(String(200), nullable=True, comment="基金管理人名称")
    
    # 基金托管人
    custodian: Mapped[Optional[str]] = mapped_column(String(200), nullable=True, comment="基金托管人")
    
    # 成立日期
    setup_date: Mapped[Optional[date]] = mapped_column(Date, nullable=True, comment="成立日期")
    
    # 上市日期
    list_date: Mapped[Optional[date]] = mapped_column(Date, nullable=True, comment="上市日期")
    
    # 到期日期
    due_date: Mapped[Optional[date]] = mapped_column(Date, nullable=True, comment="到期日期")
    
    # 基金规模（万元）
    fund_size: Mapped[Optional[Decimal]] = mapped_column(Numeric(20, 4), nullable=True, comment="基金规模(万元)")
    
    # 基金份额（万份）
    fund_share: Mapped[Optional[Decimal]] = mapped_column(Numeric(20, 4), nullable=True, comment="基金份额(万份)")
    
    # 管理费率(%)
    management_fee: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="管理费率(%)")
    
    # 托管费率(%)
    custodian_fee: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="托管费率(%)")
    
    # 销售服务费率(%)
    service_fee: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="销售服务费率(%)")
    
    # 最大申购费率(%)
    max_purchase_fee: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="最大申购费率(%)")
    
    # 最大赎回费率(%)
    max_redeem_fee: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="最大赎回费率(%)")
    
    # 基金状态：正常, 暂停申购, 暂停赎回, 清盘等
    fund_status: Mapped[str] = mapped_column(String(20), nullable=False, default="正常", comment="基金状态")
    
    # 投资目标
    invest_objective: Mapped[Optional[str]] = mapped_column(Text, nullable=True, comment="投资目标")
    
    # 投资策略
    invest_strategy: Mapped[Optional[str]] = mapped_column(Text, nullable=True, comment="投资策略")
    
    # 业绩比较基准
    benchmark: Mapped[Optional[str]] = mapped_column(Text, nullable=True, comment="业绩比较基准")
    
    # 风险等级
    risk_level: Mapped[Optional[str]] = mapped_column(String(20), nullable=True, comment="风险等级")
    
    # 扩展信息
    extra_info: Mapped[Optional[Dict[str, Any]]] = mapped_column(JSONB, nullable=True, comment="扩展信息")
    
    __table_args__ = (
        UniqueConstraint('fund_code', name='uk_fund_basic_code'),
        Index('idx_fund_basic_code', 'fund_code'),
        Index('idx_fund_basic_type', 'fund_type'),
        Index('idx_fund_basic_invest_type', 'invest_type'),
        Index('idx_fund_basic_manager', 'manager_code'),
        Index('idx_fund_basic_setup_date', 'setup_date'),
        Index('idx_fund_basic_status', 'fund_status'),
    )
    
    def __repr__(self) -> str:
        return f"<FundBasicInfo(fund_code={self.fund_code}, fund_name={self.fund_name}, fund_type={self.fund_type})>"


class FundNetValue(BaseFinancialModel, PartitionMixin):
    """
    基金净值数据模型
    存储基金的净值数据，包括单位净值、累计净值等
    """
    __tablename__ = "fund_net_value"
    
    # 基金代码
    fund_code: Mapped[str] = mapped_column(String(20), nullable=False, comment="基金代码")
    
    # 净值日期
    nav_date: Mapped[date] = mapped_column(Date, nullable=False, comment="净值日期")
    
    # 单位净值
    unit_nav: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 6), nullable=True, comment="单位净值")
    
    # 累计净值
    accum_nav: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 6), nullable=True, comment="累计净值")
    
    # 复权净值
    adj_nav: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 6), nullable=True, comment="复权净值")
    
    # 日增长率(%)
    daily_return: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="日增长率(%)")
    
    # 申购状态：开放, 暂停, 限制等
    purchase_status: Mapped[Optional[str]] = mapped_column(String(20), nullable=True, comment="申购状态")
    
    # 赎回状态：开放, 暂停, 限制等
    redeem_status: Mapped[Optional[str]] = mapped_column(String(20), nullable=True, comment="赎回状态")
    
    # 分红送配信息
    dividend_info: Mapped[Optional[str]] = mapped_column(String(200), nullable=True, comment="分红送配信息")
    
    __table_args__ = (
        UniqueConstraint('fund_code', 'nav_date', name='uk_fund_nav_code_date'),
        Index('idx_fund_nav_code', 'fund_code'),
        Index('idx_fund_nav_date', 'nav_date'),
        Index('idx_fund_nav_code_date', 'fund_code', 'nav_date'),
        # 分区索引
        Index('idx_fund_nav_partition_date', 'partition_date'),
    )
    
    def __repr__(self) -> str:
        return f"<FundNetValue(fund_code={self.fund_code}, nav_date={self.nav_date}, unit_nav={self.unit_nav})>"


class FundPortfolio(BaseFinancialModel, DataVersionMixin):
    """
    基金投资组合数据模型
    存储基金的持仓信息，包括股票、债券等资产配置
    """
    __tablename__ = "fund_portfolio"
    
    # 基金代码
    fund_code: Mapped[str] = mapped_column(String(20), nullable=False, comment="基金代码")
    
    # 报告期
    report_date: Mapped[date] = mapped_column(Date, nullable=False, comment="报告期")
    
    # 持仓类型：股票, 债券, 基金, 现金等
    holding_type: Mapped[str] = mapped_column(String(20), nullable=False, comment="持仓类型")
    
    # 证券代码
    security_code: Mapped[Optional[str]] = mapped_column(String(20), nullable=True, comment="证券代码")
    
    # 证券名称
    security_name: Mapped[Optional[str]] = mapped_column(String(200), nullable=True, comment="证券名称")
    
    # 持仓数量（股/张）
    holding_amount: Mapped[Optional[Decimal]] = mapped_column(Numeric(20, 4), nullable=True, comment="持仓数量(股/张)")
    
    # 持仓市值（元）
    holding_value: Mapped[Optional[Decimal]] = mapped_column(Numeric(20, 4), nullable=True, comment="持仓市值(元)")
    
    # 占净值比例(%)
    nav_ratio: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="占净值比例(%)")
    
    # 占股票投资比例(%)
    stock_ratio: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="占股票投资比例(%)")
    
    # 持仓排名
    holding_rank: Mapped[Optional[Integer]] = mapped_column(Integer, nullable=True, comment="持仓排名")
    
    # 行业分类
    industry: Mapped[Optional[str]] = mapped_column(String(100), nullable=True, comment="行业分类")
    
    # 持仓变动：新增, 增持, 减持, 不变
    holding_change: Mapped[Optional[str]] = mapped_column(String(20), nullable=True, comment="持仓变动")
    
    __table_args__ = (
        UniqueConstraint('fund_code', 'report_date', 'holding_type', 'security_code', 
                        name='uk_fund_portfolio_code_date_type_security'),
        Index('idx_fund_portfolio_code', 'fund_code'),
        Index('idx_fund_portfolio_date', 'report_date'),
        Index('idx_fund_portfolio_type', 'holding_type'),
        Index('idx_fund_portfolio_security', 'security_code'),
        Index('idx_fund_portfolio_industry', 'industry'),
    )
    
    def __repr__(self) -> str:
        return f"<FundPortfolio(fund_code={self.fund_code}, report_date={self.report_date}, security_code={self.security_code})>"


class FundPerformance(BaseFinancialModel, PartitionMixin):
    """
    基金业绩数据模型
    存储基金的业绩表现数据，包括各期收益率、风险指标等
    """
    __tablename__ = "fund_performance"
    
    # 基金代码
    fund_code: Mapped[str] = mapped_column(String(20), nullable=False, comment="基金代码")
    
    # 统计日期
    stat_date: Mapped[date] = mapped_column(Date, nullable=False, comment="统计日期")
    
    # 近1日收益率(%)
    return_1d: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="近1日收益率(%)")
    
    # 近1周收益率(%)
    return_1w: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="近1周收益率(%)")
    
    # 近1月收益率(%)
    return_1m: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="近1月收益率(%)")
    
    # 近3月收益率(%)
    return_3m: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="近3月收益率(%)")
    
    # 近6月收益率(%)
    return_6m: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="近6月收益率(%)")
    
    # 近1年收益率(%)
    return_1y: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="近1年收益率(%)")
    
    # 近2年收益率(%)
    return_2y: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="近2年收益率(%)")
    
    # 近3年收益率(%)
    return_3y: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="近3年收益率(%)")
    
    # 成立以来收益率(%)
    return_since_inception: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="成立以来收益率(%)")
    
    # 年化收益率(%)
    annual_return: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="年化收益率(%)")
    
    # 年化波动率(%)
    annual_volatility: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="年化波动率(%)")
    
    # 夏普比率
    sharpe_ratio: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="夏普比率")
    
    # 最大回撤(%)
    max_drawdown: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="最大回撤(%)")
    
    # 卡玛比率
    calmar_ratio: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="卡玛比率")
    
    # 索提诺比率
    sortino_ratio: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="索提诺比率")
    
    # 信息比率
    information_ratio: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="信息比率")
    
    # 贝塔系数
    beta: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="贝塔系数")
    
    # 阿尔法系数
    alpha: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="阿尔法系数")
    
    # 跟踪误差(%)
    tracking_error: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="跟踪误差(%)")
    
    # 基准收益率(%)
    benchmark_return: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="基准收益率(%)")
    
    # 超额收益率(%)
    excess_return: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="超额收益率(%)")
    
    __table_args__ = (
        UniqueConstraint('fund_code', 'stat_date', name='uk_fund_performance_code_date'),
        Index('idx_fund_performance_code', 'fund_code'),
        Index('idx_fund_performance_date', 'stat_date'),
        Index('idx_fund_performance_return_1y', 'return_1y'),
        Index('idx_fund_performance_sharpe', 'sharpe_ratio'),
        # 分区索引
        Index('idx_fund_performance_partition_date', 'partition_date'),
    )
    
    def __repr__(self) -> str:
        return f"<FundPerformance(fund_code={self.fund_code}, stat_date={self.stat_date}, return_1y={self.return_1y})>"


class FundManager(BaseFinancialModel, SyncStatusMixin):
    """
    基金经理数据模型
    存储基金经理的基本信息和管理基金情况
    """
    __tablename__ = "fund_manager"
    
    # 基金经理ID
    manager_id: Mapped[str] = mapped_column(String(20), nullable=False, comment="基金经理ID")
    
    # 基金经理姓名
    manager_name: Mapped[str] = mapped_column(String(100), nullable=False, comment="基金经理姓名")
    
    # 基金代码
    fund_code: Mapped[str] = mapped_column(String(20), nullable=False, comment="基金代码")
    
    # 任职开始日期
    start_date: Mapped[Optional[date]] = mapped_column(Date, nullable=True, comment="任职开始日期")
    
    # 任职结束日期
    end_date: Mapped[Optional[date]] = mapped_column(Date, nullable=True, comment="任职结束日期")
    
    # 任职天数
    tenure_days: Mapped[Optional[Integer]] = mapped_column(Integer, nullable=True, comment="任职天数")
    
    # 任职期间收益率(%)
    tenure_return: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="任职期间收益率(%)")
    
    # 年化收益率(%)
    annual_return: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 4), nullable=True, comment="年化收益率(%)")
    
    # 学历
    education: Mapped[Optional[str]] = mapped_column(String(50), nullable=True, comment="学历")
    
    # 从业年限
    work_years: Mapped[Optional[Integer]] = mapped_column(Integer, nullable=True, comment="从业年限")
    
    # 管理基金数量
    fund_count: Mapped[Optional[Integer]] = mapped_column(Integer, nullable=True, comment="管理基金数量")
    
    # 管理规模（万元）
    manage_scale: Mapped[Optional[Decimal]] = mapped_column(Numeric(20, 4), nullable=True, comment="管理规模(万元)")
    
    # 简介
    profile: Mapped[Optional[str]] = mapped_column(Text, nullable=True, comment="简介")
    
    __table_args__ = (
        UniqueConstraint('manager_id', 'fund_code', 'start_date', name='uk_fund_manager_id_code_start'),
        Index('idx_fund_manager_id', 'manager_id'),
        Index('idx_fund_manager_name', 'manager_name'),
        Index('idx_fund_manager_code', 'fund_code'),
        Index('idx_fund_manager_start_date', 'start_date'),
        Index('idx_fund_manager_tenure_return', 'tenure_return'),
    )
    
    def __repr__(self) -> str:
        return f"<FundManager(manager_id={self.manager_id}, manager_name={self.manager_name}, fund_code={self.fund_code})>"


class FundDividend(BaseFinancialModel):
    """
    基金分红数据模型
    存储基金的分红派息信息
    """
    __tablename__ = "fund_dividend"
    
    # 基金代码
    fund_code: Mapped[str] = mapped_column(String(20), nullable=False, comment="基金代码")
    
    # 权益登记日
    record_date: Mapped[Optional[date]] = mapped_column(Date, nullable=True, comment="权益登记日")
    
    # 除息日
    ex_date: Mapped[Optional[date]] = mapped_column(Date, nullable=True, comment="除息日")
    
    # 分红发放日
    pay_date: Mapped[Optional[date]] = mapped_column(Date, nullable=True, comment="分红发放日")
    
    # 每份分红（元）
    dividend_per_unit: Mapped[Optional[Decimal]] = mapped_column(Numeric(10, 6), nullable=True, comment="每份分红(元)")
    
    # 分红类型：现金分红, 红利再投资
    dividend_type: Mapped[Optional[str]] = mapped_column(String(20), nullable=True, comment="分红类型")
    
    # 分红总额（万元）
    total_dividend: Mapped[Optional[Decimal]] = mapped_column(Numeric(20, 4), nullable=True, comment="分红总额(万元)")
    
    # 分红说明
    dividend_note: Mapped[Optional[str]] = mapped_column(Text, nullable=True, comment="分红说明")
    
    __table_args__ = (
        UniqueConstraint('fund_code', 'record_date', name='uk_fund_dividend_code_record_date'),
        Index('idx_fund_dividend_code', 'fund_code'),
        Index('idx_fund_dividend_record_date', 'record_date'),
        Index('idx_fund_dividend_ex_date', 'ex_date'),
        Index('idx_fund_dividend_pay_date', 'pay_date'),
    )
    
    def __repr__(self) -> str:
        return f"<FundDividend(fund_code={self.fund_code}, record_date={self.record_date}, dividend_per_unit={self.dividend_per_unit})>"


# 导出所有基金相关模型
__all__ = [
    'FundBasicInfo',
    'FundNetValue',
    'FundPortfolio',
    'FundPerformance',
    'FundManager',
    'FundDividend',
]